# 序列化器类用与将python类型的数据转换为json格式的数据

from rest_framework import serializers

from drfstudy.models import Student, Classes

# class StudentSerializer(serializers.Serializer):
#     id = serializers.IntegerField(label='ID', read_only=True)
#     name = serializers.CharField(label="姓名", max_length=20)
#     # required=False 年龄这个字段值不是必填项
#     age = serializers.IntegerField(label="年龄", required=False)
#     sex = serializers.IntegerField(label="性别", required=False)
#
#     # create_time = serializers.DateTimeField(label='创建时间', required=False)
#     # update_time = serializers.DateTimeField(label='修改时间', required=False)
#     # is_delete = serializers.BooleanField(default=False, label="逻辑删除", required=False)
#
#     # validated_data 前端传入的数据 是一个字典格式的 键值对格式的 key=value
#     def create(self, validated_data):
#         return Student.objects.create(**validated_data)
#
#     def update(self, instance, validated_data):
#         # instance 数据库的模型对象 学生对象
#         # validated_data 前端传过来的数据
#         instance.name = validated_data.get("name", instance.name)
#         instance.age = validated_data.get("age", instance.age)
#         instance.sex = validated_data.get("sex", instance.sex)
#         # 模型对象在调用save方法 做数据的保存更新
#         instance.save()
#         return instance


"""
序列化器的两个功能
功能一：对用户提交的数据进行校验 - 反序列化
校验前端的数据是否符合格式规则 长度 是否空
功能二：对要返回的数据进行指定 - 序列化
serializer.data
将查询到的数据库的数据转换为json格式的数据响应给到前端
"""


# 如果自定义的序列化器拥有对应的模型类 就会把模型类里面的字段自动全部映射到序列化器里面
class StudentSerializer(serializers.ModelSerializer):
    # 模型类里面没有的字段，但是又需要展示的字段 可以自定义
    # source 字段值来自什么地方 classes.name通过两表联查找到对应的值
    # read_only=True 只能查看 不能修改
    # 班级名只会有一个
    class_name = serializers.CharField(source='classes.name', read_only=True)

    # 定义元信息类
    class Meta:
        # 把student模型类映射创建序列化器类型
        model = Student
        # 显示所有的映射字段
        # fields = '__all__'
        # 指定显示的字段
        # fields = ['name','age']
        # 指定不显示的字段
        exclude = ('is_delete', 'create_time', 'update_time')

        # 添加额外的数据格式校验 修改校验的规则
        extra_kwargs = {
            "age": {
                "min_value": 14,
                "max_value": 100,
            },
            # 设置为只写字段 一个只能修改
            # 因为classes在模型类里面定义了，会帮我们自动隐射到序列化器
            # 所以不需要额外手动定义该字段 所以我们在序列化器里面不能直接看到该字段的定义
            # 写在了 额外的数据格式校验中
            "classes": {"write_only": True},
        }

    # 属性级别的校验 只能一次性校验一个指定字段的值
    # value保存了前端传过来的值
    # validate_字段名 你想要校验的字段名
    def validate_name(self, value):
        # 想要学生的名字包含drf字母
        if 'drf' not in value.lower():
            raise serializers.ValidationError("学生名需要包含drf字母")
        # 如果该字段值没有问题 需要返回
        return value.upper()

    # 对象级别的校验 可以同时校验多个字段值
    # 对 年龄和姓名两个字段做值的校验
    # attrs 字典 通过get取值
    # def validate(self, attrs):
    #     if 'python' not in attrs.get('name').lower():
    #         raise serializers.ValidationError("学生名需要包含python字母")
    #
    #     if attrs.get("age") < 18:
    #         raise serializers.ValidationError("年龄大于18岁才能注册")
    #     # 如果需要校验的字段没问题 返回
    #     return attrs


# 专门用于在班级显示学生信息
class StudentSerializerSimple(serializers.ModelSerializer):
    class Meta:
        model = Student
        fields = ['id', 'name', 'age']


class ClassSerializer(serializers.ModelSerializer):
    # student_set是一对多的管理器的名字
    # 序列化器的嵌套 在班级的序列化器里面 嵌套了学生的序列化器的使用
    # 把该班级的所有学生数据交给学生序列化器进行序列化的操作，序列化后的数据放到student_set管理器属性中
    # 学生是有多个的
    student_set = StudentSerializerSimple(many=True, read_only=True)

    class Meta:
        model = Classes
        exclude = ('is_delete', 'create_time', 'update_time')
